/*
 * ChannelElement.java
 *
 * Created on August 18, 2007, 4:47 PM
 *
 *  Copyright (C) 2010 Tal Eisenberg
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package tal.drivechain.wildcard;

import tal.drivechain.chain.ChainNode;
import tal.drivechain.wildcard.Wildcard.Operator;
import tal.drivechain.plugin.Channel;

/**
 * A WildcardElement class for using channel types as elements.
 * for example: [chain], [!global], [chain;globalmsg] etc.
 * 
 * @author Tal Eisenberg
 */
public class ChannelElement implements WildcardElement {
    Channel channel;
    
    public void parse(String element) throws IllegalArgumentException {
        channel = Channel.findChannel(element);
    }

    public boolean matches(Object value, ChainNode context) {
        try {
            return (Channel)value == channel;
        } catch (ClassCastException ce) {
            throw new IllegalArgumentException("This wildcard can only match channel type codes.");
        }
    }

    public boolean validOperator(Operator opcode) {
        switch (opcode) {
            case AND:
            case ANY:
            case NOT:
            case ELEMENT:
            case OR:
                return true;
            default: 
                return false;
        }
    }

    public WildcardElement makeWildcardElement(String element) {
        ChannelElement ret = new ChannelElement();
        ret.parse(element);
        return ret;
    }

    public Object getValue(ChainNode context) {
        return this.channel;
    }

    public boolean matchesElementFormat(String wc) {
        try {
            Channel.findChannel(wc);
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    public String toString(ChainNode context) {
        return channel.getName();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof ChannelElement) {
            if (super.equals(obj)) return true;
            else {
                ChannelElement that = (ChannelElement)obj;
                return (this.channel.equals(that.channel));
            }
        } else return false;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 29 * hash + (this.channel != null ? this.channel.hashCode() : 0);
        return hash;
    }

}
